package com.chuangyiruanke.util;

import javax.naming.SizeLimitExceededException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Base64;

/**
 * 网络流读取工具
 * @author zxh
 */
public class NetworkStreamUtil {

  /**
   * 从网络文件流中读取指定长度的内容
   *
   * @param networkStream 网络文件流
   * @param readLength    读取长度
   * @param buffer        存储读取结果的数组
   * @param startIndex    从此位置开始存储
   * @return 实际读取的长度
   */
  public static int readStream(InputStream networkStream, int readLength, byte[] buffer, int startIndex) throws IOException {
    int readed = 0;
    // 总可存储长度
    int totalLength = buffer.length - startIndex;
    if (readLength <= 0 || totalLength <= 0) {
      return readed;
    }
    int index = startIndex;

    int next = networkStream.read();
    while (next > -1 && ++readed < totalLength) {
      buffer[index] = (byte) next;
      index++;

      int len = networkStream.read(buffer, index, totalLength - readed);
      readed += len;
      index += len;
      if (readed == totalLength) {
        break;
      }
      next = networkStream.read();
    }
    return readed;
  }

  /**
   * 从网络文件流中读取指定长度的内容
   *
   * @param networkStream 网络文件流
   * @param readLength    读取长度
   * @param buffer        存储读取结果的数组
   * @return 实际读取的长度
   */
  public static int readStream(InputStream networkStream, int readLength, byte[] buffer) throws IOException {
    return readStream(networkStream, readLength, buffer, 0);
  }

  /**
   * 从网络文件流中读取内容并存储到指定位置
   *
   * @param networkStream 网络文件流
   * @param buffer        存储读取结果的数组
   * @param startIndex    从此位置开始存储
   * @return 实际读取的长度
   */
  public static int readStream(InputStream networkStream, byte[] buffer, int startIndex) throws IOException {
    return readStream(networkStream, buffer.length - startIndex, buffer, startIndex);
  }

  /**
   * 从网络文件流中读取指定数组长度的内容
   *
   * @param networkStream 网络文件流
   * @param buffer        存储读取结果的数组
   * @return 实际读取的长度
   */
  public static int readStream(InputStream networkStream, byte[] buffer) throws IOException {
    return readStream(networkStream, buffer.length, buffer, 0);
  }

  /**
   * 将网络流从当前读取位置开始，转换为等价的 Base64 字符串
   *
   * @param networkStream 网络文件流
   * @return 转换后的 Base64 字符串
   * @throws IOException
   */
  public static String toBase64(InputStream networkStream) throws IOException {
    int len;
    byte[] buffer = new byte[8133];
    java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
    StringBuilder builder = new StringBuilder(512000);
    while ((len = readStream(networkStream, buffer)) > 0) {
      if (len == 8133) {
        builder.append(encoder.encodeToString(buffer));
      } else {
        byte[] copy = Arrays.copyOfRange(buffer, 0, len);
        builder.append(encoder.encodeToString(copy));
      }
    }
    return builder.toString();
  }

  /**
   * 将网络流从当前读取位置开始，转换为等价的 Base64 字符串
   *
   * @param networkStream 网络文件流
   * @param maxLength     Base64 字符串的最大长度
   * @return 转换后的 Base64 字符串
   * @throws IOException
   */
  public static String toBase64(InputStream networkStream, int maxLength) throws IOException, SizeLimitExceededException {
    int len;
    byte[] buffer = new byte[8133];
    java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
    StringBuilder builder = new StringBuilder(512000);
    while ((len = readStream(networkStream, buffer)) > 0) {
      if (len == 8133) {
        builder.append(encoder.encodeToString(buffer));
      } else {
        byte[] copy = Arrays.copyOfRange(buffer, 0, len);
        builder.append(encoder.encodeToString(copy));
      }
      if (builder.length() > maxLength) {
        throw new SizeLimitExceededException();
      }
    }
    return builder.toString();
  }
}
